home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™94 / Talks & Papers / Michael D. Crawford↵ / Word Services SDK 1.0.5 / Writeswell Jr. Source / MyFiles.c < prev    next >
Text File  |  1993-03-17  |  10KB  |  504 lines

  1. /* MyFiles.c
  2.  * Handle file calls in IAC speller testbed app
  3.  * ©1992 Working Software, Inc.
  4.  * This source code is copyrighted.  Permission is granted to use the Word Services
  5.  * portion of the Writeswell Jr. source code in your own programs, but you 
  6.  * may not distribute the Writeswell Jr. word-processor code as a 
  7.  * commercial product.  If you modify the code, please do not call it 
  8.  * Writeswell Jr. (or Writeswell.)  This will ensure that people understand the 
  9.  * program and don’t have to deal with a number of different versions with 
  10.  * who-knows-what going on in the code.
  11.  * 
  12.  * Writeswell Jr. and Writeswell are trademarks of Working Software, Inc.
  13.  * 6 Sep 91 Mike Crawford
  14.  */
  15.  
  16. #include <Files.h>
  17. #include "MyFiles.h"
  18. #include "AppleEvents.h"
  19. #include "TBConstants.h"
  20. #include "TBGlobals.h"
  21. #include "TestBed.h"
  22. #include "Scroll.h"
  23. #include "Gripe.h"
  24. #include "FontMenu.h"
  25.  
  26. #define kZoomIconAllowance    68        /* Width of desktop to show when window zoomed */
  27.  
  28. OSErr SaveStyleResource( void );
  29. Boolean AskSave( void );
  30.  
  31. void DoOpenDialog( void )
  32. {
  33.     SFTypeList    typeList;
  34.     SFReply        reply;
  35.     Point        where;
  36.     OSErr        err;
  37.     
  38.     typeList[ 0 ] = 'TEXT';
  39.  
  40.     /* STUB Center the dialog */
  41.     
  42.     where.h = 50;
  43.     where.v = 50;
  44.  
  45.     SFGetFile( where,
  46.                     "\p",
  47.                     (FileFilterProcPtr)NULL,
  48.                     1,
  49.                     typeList,
  50.                     (DlgHookProcPtr)NULL,
  51.                     &reply );
  52.     
  53.     if ( !reply.good )
  54.         return;
  55.     
  56.     MyOpenSfFile( &reply );
  57.  
  58.     return;
  59. }
  60.  
  61. void DoSave( void )
  62. {
  63.     Boolean    saved;
  64.  
  65.     if ( gDocExists )
  66.         SaveFile();
  67.     else
  68.         DoSaveDialog( &saved );
  69.     return;
  70. }
  71.  
  72. OSErr DoSaveAs( void )
  73. {
  74.     OSErr    err;
  75.     short    oldRefNum;
  76.     short    oldResRefNum;
  77.     Boolean    docExisted;
  78.     Boolean    saved;
  79.     
  80.     docExisted = gDocExists;
  81.     
  82.     if ( docExisted ){
  83.         oldRefNum = gRefNum;
  84.         oldResRefNum = gResRefNum;
  85.     }
  86.     
  87.     err = DoSaveDialog( &saved );
  88.     
  89.     if ( docExisted && saved ){
  90.         err = FSClose( oldRefNum );
  91.         if ( err ){
  92.             Gripe( "\pCould not close original file" );
  93.             return err;
  94.         }
  95.         
  96.         if ( oldResRefNum != -1 ){
  97.             CloseResFile( oldResRefNum );
  98.             err = ResError();
  99.             if ( err ){
  100.                 Gripe( "\pCould not close original resource file" );
  101.                 return err;
  102.             }
  103.         }
  104.     }
  105.  
  106.     return noErr;
  107. }
  108.  
  109.  
  110. OSErr DoSaveDialog( Boolean *savedPtr )
  111. {
  112.     SFReply        reply;
  113.     OSErr        err;
  114.     Point        where;
  115.     
  116.     *savedPtr = false;
  117.  
  118.     /* STUB Center the dialog on the screen */
  119.     
  120.     where.h = 100;
  121.     where.v = 50;
  122.  
  123.     /* STUB use the window name as the default name */
  124.     
  125.     SFPutFile( where,
  126.                 "\pSave document as:",
  127.                 "\pUntitled",
  128.                 (ProcPtr)NULL,
  129.                 &reply );
  130.     
  131.     if ( !reply.good )
  132.         return noErr;
  133.     
  134.     /* Try deleting the old file.  It may not exist.
  135.      * STUB Do a GetFileInfo to see if the file already exists
  136.      */
  137.     
  138.     err = FSDelete( reply.fName, reply.vRefNum );
  139.     if ( err && err != fnfErr ){
  140.         Gripe( "\pCould not delete existing file" );
  141.         return err;
  142.     }
  143.     
  144.     err = Create( reply.fName,
  145.                     reply.vRefNum,
  146.                     'MiKe',
  147.                     'TEXT' );
  148.     if ( err ){
  149.         Gripe( "\pCould not create new file" );
  150.         return err;
  151.     }
  152.     
  153.     if ( err = FSOpen( reply.fName, reply.vRefNum, &gRefNum ) ){
  154.         Gripe( "\pFSOpen failed" );
  155.         return err;
  156.     }
  157.     
  158.     err = SetVol( (StringPtr)NULL, reply.vRefNum );
  159.     if ( err ){
  160.         Gripe( "\pCould not set volume" );
  161.         return err;
  162.     }
  163.  
  164.     CreateResFile( reply.fName );
  165.     if ( err = ResError() ){
  166.         Gripe( "\pCould not create resource fork of document" );
  167.         return err;
  168.     }
  169.  
  170.     gResRefNum = OpenResFile( reply.fName );
  171.     if ( gResRefNum == -1 ){
  172.         err = ResError();
  173.         Gripe( "\pOpenResFile failed" );
  174.         return err;
  175.     }
  176.  
  177.     gDocExists = true;
  178.     
  179.     err = SaveFile();
  180.  
  181.     if ( !err ){
  182.         SetWTitle( gDocWindow, reply.fName );
  183.         *savedPtr = true;
  184.     }
  185.  
  186.     return err;
  187. }
  188.  
  189. OSErr SaveFile( void )
  190. {
  191.     OSErr        err;
  192.     TEHandle    textH;
  193.     CharsHandle    textBufHdl;
  194.     long        numChars;
  195.  
  196.     /* STUB should do a "safe save" here.  This is not a safe save - if there is 
  197.      * a failure in here, the file is hosed.
  198.      */
  199.  
  200.     err = SetFPos( gRefNum, fsFromStart, 0L );
  201.     if ( err ){
  202.         Gripe( "\pCould not set file position" );
  203.         return err;
  204.     }
  205.  
  206.     err = SetEOF( gRefNum, 0L );
  207.     if ( err ){
  208.         Gripe( "\pCould not set end of file" );
  209.         return err;
  210.     }
  211.  
  212.     textH = (TEHandle)GetWRefCon( gDocWindow );
  213.     
  214.     textBufHdl = TEGetText( textH );
  215.     
  216.     numChars = GetHandleSize( textBufHdl );
  217.     
  218.     HLock( textBufHdl );
  219.     err = FSWrite( gRefNum, &numChars, *textBufHdl );
  220.     HUnlock( textBufHdl );
  221.     
  222.     if ( err ){
  223.         Gripe( "\pFSWrite failed" );
  224.         return err;
  225.     }
  226.     
  227.     err = SaveStyleResource();
  228.     
  229.     if ( !err )
  230.         gDocDirty = false;
  231.  
  232.     return err;
  233. }
  234.  
  235. OSErr SaveStyleResource( void )
  236. {
  237.     short            curFile;
  238.     StScrpHandle    styleHdl;
  239.     TEHandle        textH;
  240.     Handle            oldStyle;
  241.     short            oldStart;
  242.     short            oldEnd;
  243.     
  244.     curFile = CurResFile();
  245.     
  246.     UseResFile( gResRefNum );
  247.     
  248.     textH = (TEHandle)GetWRefCon( gDocWindow );
  249.     
  250.     oldStart = (*textH)->selStart;
  251.     oldEnd = (*textH)->selEnd;
  252.  
  253.     (*textH)->selStart = 0;
  254.     (*textH)->selEnd = 32767;
  255.  
  256.     styleHdl = GetStylScrap( textH );
  257.     
  258.     (*textH)->selStart = oldStart;
  259.     (*textH)->selEnd = oldEnd;
  260.  
  261.     if ( !styleHdl ){
  262.         UseResFile( curFile );
  263.         return memFullErr;
  264.     }
  265.     
  266.     oldStyle = Get1Resource( 'styl', rStyleID );
  267.     
  268.     if ( oldStyle ){
  269.         RmveResource( oldStyle );    
  270.     }
  271.  
  272.     AddResource( styleHdl, 'styl', rStyleID, "\pText Styles" );
  273.     ChangedResource( styleHdl );
  274.     WriteResource( styleHdl );
  275.  
  276.     UpdateResFile( gResRefNum );
  277.  
  278.     UseResFile( curFile );
  279.  
  280.     return noErr;
  281. }
  282.  
  283. OSErr MyOpenSfFile( SFReply *replyPtr )
  284. {
  285.     OSErr            err;
  286.     Rect            txRect;
  287.     char            *textBuf;
  288.     long            bytesRead;
  289.     TEHandle        textH;
  290.     StScrpHandle    styleHdl;
  291.     ParamBlockRec    fPB;
  292.     long            fileSize;
  293.     
  294.     if ( err = FSOpen( replyPtr->fName, replyPtr->vRefNum, &gRefNum ) ){
  295.         Gripe( "\pFSOpen failed" );
  296.         return err;
  297.     }
  298.     
  299.     fPB.fileParam.ioCompletion = (ProcPtr)NULL;
  300.     fPB.fileParam.ioNamePtr = (StringPtr)NULL;
  301.     fPB.fileParam.ioVRefNum = replyPtr->vRefNum;
  302.     
  303.     err = PBSetVol( &fPB, false );
  304.     if ( err ){
  305.         Gripe( "\pPBSetVol failed in MyOpenSfFile" );
  306.         return err;
  307.     }
  308.  
  309.     gResRefNum = OpenResFile( replyPtr->fName );
  310.     
  311.     /* The existing file may have had no resource fork.  It's not clear to me
  312.      * what the right thing to do is.  I am inclined to not create one - if the
  313.      * user wants to save styles, she could do a "Save As" to create a new file
  314.      * with the style resource.
  315.      */
  316.  
  317.     styleHdl = (StScrpHandle)NULL;            /* In case there's no resource fork */
  318.  
  319.     if ( gResRefNum != -1 ){
  320.  
  321.         /* Load the style resource */
  322.         
  323.         styleHdl = (StScrpHandle)Get1Resource( 'styl', rStyleID );
  324.         
  325.         /* styleHdl might be nil - we check for this later */
  326.     }
  327.     
  328.     if ( MakeNewWindow() ){
  329.         Gripe( "\pMakeNewWindow failed" );
  330.         return err;
  331.     }
  332.     
  333.     gDocExists = true;
  334.  
  335.     SetWTitle( gDocWindow, replyPtr->fName );
  336.  
  337.     textH = (TEHandle)GetWRefCon( gDocWindow );
  338.  
  339.     /* Styled TextEdit requires that we insert the text and the style at the same time.
  340.      * I originally had a loop that did a read with a small buffer, but in order to
  341.      * set both the text and the style, I need to read all of the text in a single
  342.      * chunk, and set it in a single chunk.
  343.      */
  344.     
  345.     err = GetEOF( gRefNum, &fileSize );
  346.     if ( err ){
  347.         Gripe( "\pCould not get file size" );
  348.         return err;
  349.     }
  350.  
  351.     textBuf = NewPtr( fileSize );
  352.     if ( !textBuf ){
  353.         Gripe( "\pOut of memory" );
  354.         return memFullErr;
  355.     }
  356.  
  357.     bytesRead = fileSize;
  358.  
  359.     err = FSRead( gRefNum, &bytesRead, textBuf );
  360.     
  361.     if ( err ){
  362.         Gripe( "\pCould not read the file" );
  363.         DisposPtr( textBuf );
  364.         return err;
  365.     }
  366.     
  367.     /* styleHdl might be nil.  This is OK */
  368.     TEStylInsert( textBuf, bytesRead, styleHdl, textH );
  369.     
  370.     if ( styleHdl != (StScrpHandle)NULL );
  371.         ReleaseResource( styleHdl );
  372.  
  373.     TESetSelect( 0L, 0L, textH );
  374.  
  375.     SetVertScroll( gDocWindow, gVertScroll );
  376.  
  377.     return noErr;
  378. }
  379.  
  380. OSErr MyOpenSpecFile( FSSpec *specPtr )
  381. {
  382.     WDPBRec            wPB;
  383.     SFReply            reply;
  384.     OSErr            err;
  385.     
  386.     wPB.ioCompletion = (ProcPtr)NULL;
  387.     wPB.ioVRefNum = specPtr->vRefNum;
  388.     wPB.ioWDDirID = specPtr->parID;
  389.     wPB.ioWDProcID = 'ERIK';            /* This is traditional; no real point to it */
  390.     wPB.ioNamePtr = (StringPtr)NULL;
  391.  
  392.     err = PBOpenWD( &wPB, false );
  393.     if ( err ){
  394.         Gripe( "\pPBOpenWD failed in MyOpenSpecFile" );
  395.         return err;
  396.     }
  397.     
  398.     BlockMove( specPtr->name, reply.fName, (specPtr->name)[0] + 1 );
  399.     
  400.     reply.vRefNum = wPB.ioVRefNum;
  401.     
  402.     reply.good = true;
  403.     
  404.     reply.copy = false;
  405.     
  406.     reply.fType = 'TEXT';            /* STUB Do a GetFileInfo to find the type */
  407.     
  408.     reply.version = 0;
  409.     
  410.     err = MyOpenSfFile( &reply );
  411.     
  412.     return err;
  413. }
  414.  
  415. OSErr MakeNewWindow( void )
  416. {
  417.     OSErr        err;
  418.     Rect        txRect;
  419.     TEHandle    textH;
  420.     Rect        *zoomArray;
  421.  
  422.     gDocWindow = GetNewWindow( kDocWindowID, (Ptr)NULL, (WindowPtr) -1 );
  423.     if ( !gDocWindow ){
  424.         Gripe( "\pGetNewWindow failed" );
  425.         return err;
  426.     }
  427.     
  428.     SetPort( gDocWindow );
  429.     
  430.     gDocDirty = false;
  431.     gDocExists = false;
  432.     
  433.     GetTERect( &( thePort->portRect ), &txRect );
  434.     
  435.     textH = TEStylNew( &txRect, &txRect );
  436.     
  437.     if ( !textH ){
  438.         Gripe( "\pTENew failed" );
  439.         return memFullErr;
  440.     }
  441.     
  442.     SetWRefCon( gDocWindow, (long)textH );
  443.     
  444.     gVertScroll = GetNewControl( kVertScrollBarID, gDocWindow );
  445.     if ( !gVertScroll )
  446.         return memFullErr;
  447.  
  448.     ( *textH )->clikLoop = (ProcPtr)TrackContentClick;
  449.  
  450.     SizeVertScroll();
  451.  
  452.     SetVertScroll( gDocWindow, gVertScroll );
  453.     
  454.     if ( ((WindowPeek)gDocWindow)->dataHandle != (Handle)NULL ){
  455.         /* Set the zoom state to reveal the disk & trash icons.
  456.          * STUB Make this some kind of preference - inappropriate for Unifinder
  457.          */
  458.     
  459.         zoomArray = (Rect*)*((WindowPeek)gDocWindow)->dataHandle;        /* Warning: Deref handle */
  460.         
  461.         zoomArray[ 1 ].right -= kZoomIconAllowance;
  462.     }
  463.  
  464.     return noErr;
  465.     
  466. }
  467.  
  468. void DoCloseWindow( void )
  469. {
  470.     Boolean saveIt;
  471.     
  472.     if ( gDocDirty ){
  473.         saveIt = AskSave();
  474.         if ( saveIt )
  475.             DoSave();
  476.     }
  477.  
  478.     TEDispose( (TEHandle)GetWRefCon( gDocWindow) );
  479.     DisposeWindow( gDocWindow );        
  480.     gDocWindow = (WindowPtr)NULL;
  481.     
  482.     if ( gDocExists ){
  483.         /* If the file exists on disk, close it */
  484.         FSClose( gRefNum );
  485.         if ( gResRefNum != -1 )
  486.             CloseResFile( gResRefNum );
  487.     }
  488.  
  489.     FixMenuMarks();            /* Disable menu items to reflect absent window */
  490.  
  491.     return;
  492. }
  493.  
  494. Boolean AskSave( void )
  495. {
  496.     short    item;
  497.     
  498.     item = Alert( rAskSaveID, (ProcPtr)NULL );
  499.  
  500.     if ( item == kASSave )
  501.         return true;
  502.     
  503.     return false;
  504. }